package com.imageflowpro.image_flow_pro.service.impl;

import com.baomidou.mybatisplus.extension.toolkit.Db;
import com.imageflowpro.image_flow_pro.constant.JwtClaimsConstant;
import com.imageflowpro.image_flow_pro.context.BaseContext;
import com.imageflowpro.image_flow_pro.dto.UserUploadImageDTO;
import com.imageflowpro.image_flow_pro.exception.BaseException;
import com.imageflowpro.image_flow_pro.exception.LoginFailedException;
import com.imageflowpro.image_flow_pro.po.MediaImage;
import com.imageflowpro.image_flow_pro.mapper.MediaImageMapper;
import com.imageflowpro.image_flow_pro.po.User;
import com.imageflowpro.image_flow_pro.po.VerificationCode;
import com.imageflowpro.image_flow_pro.properties.JwtProperties;
import com.imageflowpro.image_flow_pro.properties.MinioProperties;
import com.imageflowpro.image_flow_pro.service.IMediaImageService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.imageflowpro.image_flow_pro.service.IUserService;
import com.imageflowpro.image_flow_pro.utils.JwtUtil;
import com.imageflowpro.image_flow_pro.utils.MinioUtil;
import com.imageflowpro.image_flow_pro.vo.UserUploadImageVO;
import io.jsonwebtoken.Claims;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.InputStreamResource;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;

/**
 * <p>
 * 图片存储表 服务实现类
 * </p>
 *
 * @author 张家浩
 * @since 2025-05-07
 */
@Service
@Slf4j
public class MediaImageServiceImpl extends ServiceImpl<MediaImageMapper, MediaImage> implements IMediaImageService {

    @Autowired
    private MinioUtil minioUtil;
    @Autowired
    private MinioProperties minioProperties;
    @Autowired
    private JwtProperties jwtProperties;
    @Autowired
    private IUserService iUserService;


    @Override
    @Transactional
    public UserUploadImageVO userUploadImage(UserUploadImageDTO userUploadImageDTO) {
        if((userUploadImageDTO.getMinioName()==null&&userUploadImageDTO.getId()!=null)||(userUploadImageDTO.getMinioName()!=null&&userUploadImageDTO.getId()==null)){
            throw new BaseException("请传入完整参数");
        }
        if(userUploadImageDTO.getFile()==null){
            throw new BaseException("文件为空");
        }
        String fileName = userUploadImageDTO.getFile().getOriginalFilename();
        String minionName= String.valueOf(UUID.randomUUID());
        MediaImage mediaImage = new MediaImage();
        fileName=minionName+fileName.substring(fileName.lastIndexOf("."));
        if(userUploadImageDTO.getMinioName()!=null){
            MediaImage image = this.lambdaQuery()
                    .eq(MediaImage::getId, userUploadImageDTO.getId())
                    .one();
            if(image==null){
                throw new BaseException("要求修改的文件不存在");
            }
            if (image.getVerificationId()==-1){
                throw new BaseException("此图片已经提交，不允许修改");
            }
            VerificationCode verificationCode = Db.lambdaQuery(VerificationCode.class)
                    .eq(VerificationCode::getId, image.getVerificationId())
                    .one();
            if(verificationCode==null||!LocalDateTime.now().isBefore(verificationCode.getExpireAt())){
                throw new BaseException("该验证码已经过期");
            }
            fileName=userUploadImageDTO.getMinioName();
            mediaImage=this.getById(userUploadImageDTO.getId());
        }
//        fileName=minionName;
        log.error("fileName:"+fileName);
        minioUtil.minioUpload(userUploadImageDTO.getFile(), BaseContext.getCurrentId()+"/"+fileName,minioProperties.getBucketName());
        mediaImage.setMinioName(fileName);
        mediaImage.setUploadBy(BaseContext.getCurrentId());
        if(mediaImage.getVerificationId()==null){
            VerificationCode verificationCode = Db.lambdaQuery(VerificationCode.class)
                    .eq(VerificationCode::getId, userUploadImageDTO.getVerificationId())
                    .one();
            if(verificationCode==null||!LocalDateTime.now().isBefore(verificationCode.getExpireAt())){
                throw new BaseException("该验证码已经过期");
            }
            mediaImage.setVerificationId(userUploadImageDTO.getVerificationId());
        }
        this.saveOrUpdate(mediaImage);
        UserUploadImageVO userUploadImageVO = new UserUploadImageVO();
        userUploadImageVO.setId(mediaImage.getId());
        userUploadImageVO.setMinioName(mediaImage.getMinioName());
        return userUploadImageVO;
    }

    @Override
    public void getImageById(HttpServletResponse response, Long imageId) {
        MediaImage image = this.getById(imageId);
        if(image==null){
            throw new BaseException("图片不存在："+imageId);
        }
        try {
            minioUtil.downloadFile(minioProperties.getBucketName(),image.getUploadBy()+"/"+image.getMinioName(),response);
        } catch (Exception e) {
            throw new BaseException(e.getMessage());
        }
    }

    @Override
    @Transactional
    public void deleteImageById(Long imageId) {
        MediaImage image = this.lambdaQuery()
                .eq(MediaImage::getUploadBy, BaseContext.getCurrentId())
                .eq(MediaImage::getId, imageId)
                .one();
        if(image==null){
            throw new BaseException("图片不存在，id:"+imageId+",userId:"+BaseContext.getCurrentId());
        }
        if(image.getOrderId()!=null){
            throw new BaseException("该图片已经提交订单，无法单独删除");
        }
        minioUtil.deleteFile(minioProperties.getBucketName(),BaseContext.getCurrentId()+"/"+image.getMinioName());
        this.removeById(imageId);
    }

    @Override
    public ResponseEntity<InputStreamResource> userDownloadImages(String orderId) {

        List<MediaImage> mediaImageList = Db.lambdaQuery(MediaImage.class)
                .eq(MediaImage::getOrderId, orderId)
                .eq(MediaImage::getUploadBy,BaseContext.getCurrentId())
                .list();
        if(mediaImageList==null){
            throw new BaseException("订单中没有图片");
        }
        List<String> mediaImageNameList=new ArrayList<>();
        mediaImageList.forEach(mediaImage -> mediaImageNameList.add(BaseContext.getCurrentId()+"/"+mediaImage.getMinioName()));
        return minioUtil.downloadFilesAsZip(minioProperties.getBucketName(),mediaImageNameList);
    }

    @Override
    public ResponseEntity<InputStreamResource> adminDownloadImages(String orderId) {
        List<MediaImage> mediaImageList = Db.lambdaQuery(MediaImage.class)
                .eq(MediaImage::getOrderId, orderId)
                .list();
        if(mediaImageList==null){
            throw new BaseException("订单中没有图片");
        }
        List<String> mediaImageNameList=new ArrayList<>();
        mediaImageList.forEach(mediaImage -> mediaImageNameList.add(mediaImage.getUploadBy()+"/"+mediaImage.getMinioName()));
        return minioUtil.downloadFilesAsZip(minioProperties.getBucketName(),mediaImageNameList);
    }

    @Override
    public ResponseEntity<InputStreamResource> adminWXDownloadImages(String orderId, String token) {
        Claims claims = JwtUtil.parseJWT(jwtProperties.getAdminSecretKey(), token);
        Long id = claims.get("id", Long.class);
        if (id == null) {
            throw new IllegalArgumentException("JWT token 缺少 'id' 字段");
        }
        log.info("当前用户id：{}", id);
        String role=iUserService.lambdaQuery()
                .eq(User::getId,id)
                .one()
                .getRole();
        //过滤非管理员用户
        if(!(role.equals(JwtClaimsConstant.ADMIN_ROLE)||role.equals(JwtClaimsConstant.SUPER_ADMIN_ROLE))){
            throw new LoginFailedException("此功能只限管理员使用");
        }
        //使用ThreadLocal传递当前登录用户的ID
        BaseContext.setCurrentId(id);
        return this.adminDownloadImages(orderId);
    }

    @Override
    public ResponseEntity<InputStreamResource> userWXDownloadImages(String orderId, String token) {
        Claims claims = JwtUtil.parseJWT(jwtProperties.getUserSecretKey(), token);
        Long id = claims.get("id", Long.class);
        if (id == null) {
            throw new IllegalArgumentException("JWT token 缺少 'id' 字段");
        }
        log.info("当前用户id：{}", id);
        //使用ThreadLocal传递当前登录用户的ID
        BaseContext.setCurrentId(id);
        return this.userDownloadImages(orderId);
    }
}
